/* The file is saved in UTF-8 codepage.
 * Check: «Stereotype», Section mark-§, Copyright-©, Alpha-α, Beta-β, Smile-☺
 */
package cz.pecinovsky.english.lootp._134_;


import cz.pecinovsky.english.lootp._parents._ICar_134_;
import cz.pecinovsky.english.lootp.manager.Painter;
import cz.pecinovsky.english.lootp.manager.Rectangle;


import cz.pecinovsky.english.lootp.manager.CanvasManager_Envelope.               CanvasManager;

//import cz.pecinovsky.english.lootp._134_.IModulový_134_.                         IModulový;
import cz.pecinovsky.english.lootp._134_.IRotable_136_.                           IRotable;
import cz.pecinovsky.english.lootp._134_.Light_134_.                            Light;


//import cz.pecinovsky.english.lootp._134_.Car_134_.Car;
////////////////////////////////////////////////////////////////////////////////
//%%+  +++++ End of ignored starting test - place for imports +++++
//%I+ >=132z
//
//import cz.pecinovsky.english.lootp.canvasmanager.Painter;
//import cz.pecinovsky.english.lootp.canvasmanager.Rectangle;
//import cz.pecinovsky.english.lootp.canvasmanager.CanvasManager;
//%I-

import cz.pecinovsky.english.lootp.utility.NamedColor;
//%A+ >136
import cz.pecinovsky.english.lootp.utility.Area;
//%A-
import cz.pecinovsky.english.lootp.utility.Position;
//%A+ >136
import cz.pecinovsky.english.lootp.utility.Direction8;
//%A-
//%X+ xxxxx Start of the ovejumped text with declaration of the envelope xxxxx
/*******************************************************************************
 *<pre>
 * Předchozí:   oopnz._115_._116_Autor_119
 * Následující: Prozatím není
 *
 * Projekt  026z - Komentáře
 *   + Začlenění do standardní šablony + Komentáře
 *
 * Projekt  021z - Použití this
 *   ~ V prvních dvou konstruktorech nahrazena původní těla
 *     příkazem this volajícím obecnější konstruktor
 *
 * Projekt  022z - Přetěžování
 *   + Přidány další dva konstruktory
 *   ~ Ve třetím konstruktoru nahrazeno tělo příkazem this
 *     volající přidaný obecnější konstruktor
 *
 * Projekt  Ppp
 *   + Přidáno
 *   - Odebráno
 *   ~ Změněno
 *</pre>
 */
public class Car_134_
{    private Car_134_() {}   static
////////////////////////////////////////////////////////////////////////////////
//%X- ----- End of the ovejumped text with declaration of the envelope -----


/*******************************************************************************
 * Instance třídy {@code Car} představují auta směřující na východ.
 *
 * @author Rudolf PECINOVSKÝ
 * @version 6.03.2017 — 2010-11-08
 */
//%I+ <136
//public class Car implements IModulový
//%I-
//%A+ >136
public class Car implements IRotable
//%A-
//%A+ <0
        ,   _ICar_134_
//%A-
{
//== CONSTANT CLASS ATTRIBUTES =================================================

    private static final int DEFAULT_X = 0;

    private static final int DEFAULT_Y = 0;

    private static final NamedColor IMPLICITNÍ_BARVA_PODVOZKU = NamedColor.BLUE;

    private static final NamedColor BARVA_KABINY = NamedColor.GRAY;

    private static final int IMPLICITNÍ_DÉLKA = 128;
//%A+ >136

    private static final Direction8 DEFAULT_DIRECTION = Direction8.EAST;

    /** Canvas, na které se bude instance kreslit. */
    private static final CanvasManager CM = CanvasManager.getInstance();
//%A-



//== VARIABLE CLASS ATTRIBUTES =================================================

     /** Počet doposud vytvořených instancí. */
     private static int countCreated = 0;



//== STATIC CONSTRUCTOR (CLASS INITIALIZER, STATIC INICITALIZING BLOCK) ========
//== CONSTANT INSTANCE ATTRIBUTES ==============================================

    /** Pořadové (identifikační) číslo dané instance. */
    private final int ID;

    /** Podvozek auta. */
    private final Rectangle podvozek;

    /** Kabina auta. */
    private final Rectangle kabina;

    /** Levé přední light. */
    private final Light lightL;

    /** Pravé přední light. */
    private final Light lightP;



//== VARIABLE INSTANCE ATTRIBUTES ==============================================

    /** Název instance sestávající implicitně z názvu třídy a ID instance */
    private String name;
//%A+ >136

    /** Bodová x-ová souřadnice instance. */
    private int xPos;

    /** Bodová y-ová souřadnice instance. */
    private int yPos;

    /** Velikost strany čverce vyplněného šipkou v bodech. */
    private int module;

    /** Směr, do nějž je arrow natočena. */
    private Direction8 direction;
//%A-



//== CLASS GETTERS AND SETTERS =================================================
//== OTHER NON-PRIVATE CLASS METHODS ===========================================

//##############################################################################
//== CONSTUCTORS AND FACTORY METHODS ===========================================

    /***************************************************************************
     * Vytvoří car implicitních rozměrů a s implicitní barvou podvozku
     * umístěné v levém horním rohu plátna.
     */
    public Car()
    {
        this(DEFAULT_X, DEFAULT_Y);
    }


    /***************************************************************************
     * Vytvoří car implicitních rozměrů a s implicitní barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     */
    public Car(int x, int y)
    {
        this(x, y, IMPLICITNÍ_BARVA_PODVOZKU);
    }


    /***************************************************************************
     * Vytvoří car implicitních rozměrů se zadanou barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param chassisColor  Požadovaná color podvozku
     */
    public Car(int x, int y, NamedColor chassisColor)
    {
        this(x, y, IMPLICITNÍ_DÉLKA, chassisColor);
    }


    /***************************************************************************
     * Vytvoří car zadané délky s implicitní barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param module  Délka auta
     */
    public Car(int x, int y, int module)
    {
        this(x, y, module, IMPLICITNÍ_BARVA_PODVOZKU);
    }


    /***************************************************************************
     * Vytvoří car zadané délky se zadanou barvou podvozku
     * umístěné na zadaných souřadnicích.
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param module         Délka auta
     * @param chassisColor Požadovaná color podvozku
     */
    public Car(int x, int y, int module, NamedColor chassisColor)
    {
//%I+ <136
//        countCreated   = countCreated + 1;
//        this.ID = countCreated;
//
//        int d1 = module;
//        int d2 = module/2;
//        int d4 = module/4;
//        int d8 = module/8;
//
//        podvozek = new Rectangle(x,    y,    d1, d2, chassisColor);
//        kabina   = new Rectangle(x+d8, y+d8, d2, d4, BARVA_KABINY);
//
//        lightL  = new Light(x+7*d8, y,      d8);
//        lightP  = new Light(x+7*d8, y+3*d8, d8);
//    }
//%I-
//%A+ >136
        this(x, y, module, chassisColor, Direction8.EAST);
    }


    /***************************************************************************
     * Vytvoří car zadané délky se zadanou barvou podvozku
     * umístěné na zadaných souřadnicích a natočené zadaným směrem;
     *
     * @param x  Vodorovná souřadnice vytvářeného auta
     * @param y  Svislá souřadnice vytvářeného auta
     * @param module Délka auta a současně strana čtverce, v němž bude vystředěno
     * @param chassisColor Požadovaná color podvozku
     * @param direction  Směr, do nějž bude vytvořené car natočeno
     */
    public Car(int x, int y, int module, NamedColor chassisColor, Direction8 direction)
    {
        Car.countCreated = countCreated + 1;
        this.ID    = countCreated;

        this.xPos  = x;
        this.yPos  = y;
        this.module = module;
        this.direction  = direction;

        int m1 =     module;
        int m2 =     module / 2;
        int m4 =     module / 4;
        int m8 =     module / 8;
        int m38= 3 * module / 8;
        int m58= 5 * module / 8;
        int m78= 7 * module / 8;

        Area ref = new Area(x, y, module, module);
        Area díl;

        //Podvozek
        díl = new Area(0, m4, m1, m2);
        díl = direction.turnInArea(díl, ref);
        this.podvozek = new Rectangle(díl, chassisColor);

        //Kabina
        díl = new Area(m8, m38, m2, m4);
        díl = direction.turnInArea(díl, ref);
        this.kabina = new Rectangle(díl, BARVA_KABINY);

        //lightL
        díl = new Area(m78, m4, m8, m8);
        díl = direction.turnInArea(díl, ref);
        this.lightL = new Light(díl.x, díl.y, díl.height);

        //lightP
        díl = new Area(m78, m58, m8, m8);
        díl = direction.turnInArea(díl, ref);
        this.lightP = new Light(díl.x, díl.y, díl.height);
    }
//%A-



//== ABSTRACT METHODS ==========================================================
//== INSTANCE GETTERS AND SETTERS ==============================================

    // Sada přístupových metod vlastnosti: Position ******************************

    /***************************************************************************
     * Vrátí x-ovou (vodorovnou) souřadnici pozice instance.
     *
     * @return  x-ová souřadnice.
     */
//%A+ <0
    @Override
//%A-
    public int getX()
    {
//%I+ <136
//        return podvozek.getX();
//%I-
//%A+ >136
        return xPos;
//%A-
    }


    /***************************************************************************
     * Vrátí y-ovou (svislou) souřadnici pozice instance.
     *
     * @return  y-ová souřadnice.
     */
//%A+ <0
    @Override
//%A-
    public int getY()
    {
//%I+ <136
//        return podvozek.getY();
//%I-
//%A+ >136
        return yPos;
//%A-
    }


    /***************************************************************************
     * Vrátí přepravku se svojí aktuální pozicí.
     *
     * @return Aktuální pozice světla
     */
    @Override
    public Position getPosition()
    {
        return new Position(getX(), getY());
    }


    /***************************************************************************
     * Nastaví novou pozici světla.
     *
     * @param p Nastavovaná pozice
     */
    @Override
    public void setPosition(Position p)
    {
        this.setPosition(p.x, p.y);
    }


    /***************************************************************************
     * Nastaví novou pozici instance.
     *
     * @param x   Nová x-ová pozice instance
     * @param y   Nová y-ová pozice instance
     */
    @Override
    public void setPosition(int x, int y)
    {
//%I+ <136
//        int d8 = podvozek.getWidth() / 8;   //Osmina délky vozu
//
//        podvozek.setPosition(x,      y);
//        kabina  .setPosition(x+d8,   y+d8);
//        lightL .setPosition(x+7*d8, y);
//        lightP .setPosition(x+7*d8, y+3*d8);
//%I-
//%A+ >136
        int dx = x - getX();
        int dy = y - getY();
        CM.dontDraw(); {
            podvozek.moveRight(dx);       podvozek.moveDown  (dy);
            kabina  .moveRight(dx);       kabina  .moveDown  (dy);
            lightL .setPosition(lightL.getX()+dx, lightL.getY()+dy);
            lightP .setPosition(lightP.getX()+dx, lightP.getY()+dy);
        } CM.returnDraw();
        xPos = x;
        yPos = y;
//%A-
    }


    // Sada přístupových metod vlastnosti: Rozměr / Modul **********************

    /***************************************************************************
     * Vrátí základní délku, od níž se odvozují všechny rozměry objektu -
     * pro car je to jeho délka.
     *
     * @return Délka auta
     */
    @Override
    public int getModule()
    {
//%I+ <136
//        return podvozek.getWidth();
//%I-
//%A+ >136
        return module;
//%A-
    }


    /***************************************************************************
     * Nastaví nový základní rozměr instance - novou délku vozu.
     * Ostatní rozměry jsou od ní odvozené.
     *
     * @param module  Nově nastavovaná délka auta; délka > 0
     */
    @Override
    public void setModule(int module)
    {
//%A+ >139
        if (module <= 0) {
            throw new IllegalArgumentException(
                    "\nVelikost modulu musí být nezáporná - zadáno " + module);
        }
//%A-
        int x  = podvozek.getX();
        int y  = podvozek.getY();
        int m1 = module;
        int m2 = m1/2;
        int m4 = m1/4;
        int m8 = m1/8;
//%I+ <136
//
//        podvozek.setSizeInFields(m1, m2);
//
//        //U ostatních částí vozu se se změnou rozměru vozu mění i jejich pozice
//        kabina.setPosition(x+m8, y+m8);
//        kabina.setSizeInFields(m2, m4);
//
//        lightL.setPosition(x+7*m8, y);
//        lightP.setPosition(x+7*m8, y+3*m8);
//        lightL.setModule(m8);
//        lightP.setModule(m8);
//    }
//
//%I-
//%A+ >136
        int m38= 3 * m1 / 8;
        int m58= 5 * m1 / 8;
        int m78= 7 * m1 / 8;

        Area ref = new Area(xPos, yPos, module, module);
        Area díl;

        CM.dontDraw(); {
            //Podvozek
            díl = new Area(0, m4, m1, m2);
            díl = direction.turnInArea(díl, ref);
            this.podvozek.setArea(díl);

            //Kabina
            díl = new Area(m8, m38, m2, m4);
            díl = direction.turnInArea(díl, ref);
            this.kabina.setArea(díl);

            //lightL
            díl = new Area(m78, m4, m8, m8);
            díl = direction.turnInArea(díl, ref);
            this.lightL.setPosition(díl.x, díl.y);
            this.lightL.setModule(díl.height);

            //lightP
            díl = new Area(m78, m58, m8, m8);
            díl = direction.turnInArea(díl, ref);
            this.lightP.setPosition(díl.x, díl.y);
            this.lightP.setModule(díl.height);
        } CM.returnDraw();
        this.module = module;
    }


    /***************************************************************************
     * Vrátí direction, do nějž je arrow natočena.
     *
     * @return Směr, do nějž je arrow natočena
     */
    @Override
    public Direction8 getDirection()
    {
        return direction;
    }


    /***************************************************************************
     * Natočí šipku do zadaného směru.
     *
     * @param direction  Směr, do nějž se má arrow natočit
     */
    @Override
    public void setDirection(Direction8 direction)
    {
//%A-
//%A+ >139
        if (! direction.isMain()) {
            throw new IllegalArgumentException(
                "\nNebyl zadán hlavní direction - zadáno " + direction);
        }
//%A-
//%A+ >136
        this.direction = direction;
        this.setModule(module);
    }

//%A-


//== OTHER NON-PRIVATE INSTANCE METHODS ========================================

    /***************************************************************************
     * Blikne světly na levé straně auta.
     */
//%A+ <0
    @Override
//%A-
    public void blinkLeft()
    {
        lightL.blink();
    }


    /***************************************************************************
     * Blikne světly na pravé straně auta.
     */
//%A+ <0
    @Override
//%A-
    public void blinkRight()
    {
        lightP.blink();
    }


    /***************************************************************************
     * Prostřednictvím dodaného kreslítka vykreslí obraz své instance.
     *
     * @param painter Painter, které nakreslí instanci
     */
    @Override
    public void paint(Painter painter)
    {
        podvozek.paint(painter);
        kabina  .paint(painter);
        lightL .paint(painter);
        lightP .paint(painter);
    }


    /***************************************************************************
     * Zhasne všechna světla auta.
     */
//%A+ <0
    @Override
//%A-
    public void lightOn()
    {
        lightL.switchOn();
        lightP.switchOn();
    }


    /***************************************************************************
     * Zhasne všechna světla auta.
     */
//%A+ <0
    @Override
//%A-
    public void lightOff()
    {
        lightL.switchOff();
        lightP.switchOff();
    }


    /***************************************************************************
     * Vrací textovou reprezentaci (podpis) dané instance
     * používanou především k ladicím účelům.
     *
     * @return Požadovaná textová reprezentace
     */
    @Override
    public String toString()
    {
        return "Auto_" + ID + "(" + getPosition() + ", module=" + getModule() +
               ", color=" + podvozek.getColor() + ")";
    }



//== PRIVATE AND AUXILIARY CLASS METHODS =======================================
//== PRIVATE AND AUXILIARY INSTANCE METHODS ====================================
//== EMBEDDED TYPES AND INNER CLASSES ==========================================
//== TESTING CLASSES AND METHODS ===============================================
//
//    /***************************************************************************
//     * Test method.
//     */
//    public static void test()
//    {
//        Light inst = new Light();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main(String[] args)  {  test();  }
    }

//%%- ---- Start of the ovejumped text with closing of the envelope ----
////////////////////////////////////////////////////////////////////////////////

//== TESTING CLASSES AND METHODS ===============================================

    /***************************************************************************
     * Test method.
     */
    public static void test()
    {
//        new Car();
//        new Car(100, 100);
//        new Car(50, 200, NamedColor.BLACK);

        //023
        CanvasManager CM = CanvasManager.getInstance();
        CM.setStepAndSize(25, 10, 6);
        CM.setName("Auto v souřadné mřížce");
        Car a = new Car(25, 25, 200);
        CM.add(a);
//        System.exit(0);
    }
    /** @param args Parametry příkazového řádku - nepoužívané. */
    public static void main(String[] args)  {  test();  }
}
